#include "operation.h"

#include "memory.h"
#include "cpu.h"
#include "utilities.h"


ADDOperation::ADDOperation(CPU* _cpu, Memory* _memory, QObject *parent) : Operation(parent), memory(_memory), cpu(_cpu)
{
}

ADDOperation::~ADDOperation()
{
}

void ADDOperation::exec(const QString &IR)
{
    bool ok = false;
    QString SR1 = cpu->getRegister(IR.mid(6, 5).toInt(&ok, 2));
    QString SR2 = cpu->getRegister(IR.mid(11, 5).toInt(&ok, 2));
    int result = Utilities::binToDec(SR1) + Utilities::binToDec(SR2);
    QString DR = Utilities::decToBin(result);
    int DRnum = IR.mid(16, 5).toInt(&ok, 2);
    cpu->setRegisters(DRnum, DR);
}

ADDIOperation::ADDIOperation(CPU* _cpu, Memory* _memory, QObject *parent) : Operation(parent), memory(_memory), cpu(_cpu)
{
}

ADDIOperation::~ADDIOperation()
{
}

void ADDIOperation::exec(const QString &IR)
{
    bool ok;
    QString SR1 = cpu->getRegister(IR.mid(6, 5).toInt(&ok, 2));
    QString SR2 = IR.mid(16, 16);
    int result = Utilities::binToDec(SR1) + Utilities::binToDec(SR2);
    QString DR = Utilities::decToBin(result);
    int DRnum = IR.mid(11, 5).toInt(&ok, 2);
    cpu->setRegisters(DRnum, DR);
}

SUBOperation::SUBOperation(CPU* _cpu, Memory* _memory, QObject *parent) : Operation(parent), memory(_memory), cpu(_cpu)
{
}

SUBOperation::~SUBOperation()
{
}

void SUBOperation::exec(const QString &IR)
{
    bool ok;
    QString SR1 = cpu->getRegister(IR.mid(6, 5).toInt(&ok, 2));
    QString SR2 = cpu->getRegister(IR.mid(11, 5).toInt(&ok, 2));
    int result = Utilities::binToDec(SR1) - Utilities::binToDec(SR2);
    QString DR = Utilities::decToBin(result);
    int DRnum = IR.mid(16, 5).toInt(&ok, 2);
    cpu->setRegisters(DRnum, DR);
}

SUBIOperation::SUBIOperation(CPU* _cpu, Memory* _memory, QObject *parent) : Operation(parent), memory(_memory), cpu(_cpu)
{
}

SUBIOperation::~SUBIOperation()
{
}

void SUBIOperation::exec(const QString &IR)
{
    bool ok;
    QString SR1 = cpu->getRegister(IR.mid(6, 5).toInt(&ok, 2));
    QString SR2 = IR.mid(16, 16);
    int result = Utilities::binToDec(SR1) - Utilities::binToDec(SR2);
    QString DR = Utilities::decToBin(result);
    int DRnum = IR.mid(11, 5).toInt(&ok, 2);
    cpu->setRegisters(DRnum, DR);
}

ANDOperation::ANDOperation(CPU *_cpu, Memory *_memory, QObject *parent) : Operation(parent), memory(_memory), cpu(_cpu)
{
}

ANDOperation::~ANDOperation()
{
}

void ANDOperation::exec(const QString &IR)
{
    bool ok;
    QString SR1 = cpu->getRegister(IR.mid(6, 5).toInt(&ok, 2));
    QString SR2 = cpu->getRegister(IR.mid(11, 5).toInt(&ok, 2));
    QString result = "00000000000000000000000000000000";
    for (int i = 0; i < 32; i++)
    {
        if (SR1.mid(i, 1) == "1" && SR2.mid(i, 1) == "1")
            result.replace(i, 1, "1");
    }
    QString DR = result;
    int DRnum = IR.mid(16, 5).toInt(&ok, 2);
    cpu->setRegisters(DRnum, DR);
}

ANDIOperation::ANDIOperation(CPU *_cpu, Memory *_memory, QObject *parent) : Operation(parent), memory(_memory), cpu(_cpu)
{
}

ANDIOperation::~ANDIOperation()
{
}

void ANDIOperation::exec(const QString &IR)
{
    bool ok;
    QString SR1 = cpu->getRegister(IR.mid(6, 5).toInt(&ok, 2));
    QString SR2 = IR.mid(16);
    if (SR2.mid(0, 1) == "0")
    {
        SR2.prepend("0000000000000000");
    }
    else
    {
        SR2.prepend("1111111111111111");
    }
    QString result = "00000000000000000000000000000000";
    for (int i = 0; i < 32; i++)
    {
        if (SR1.mid(i, 1) == "1" && SR2.mid(i, 1) == "1")
        {
            result.replace(i, 1, "1");
        }
    }
    QString DR = result;
    int DRnum = IR.mid(11, 5).toInt(&ok, 2);
    cpu->setRegisters(DRnum, DR);
}

OROperation::OROperation(CPU *_cpu, Memory *_memory, QObject *parent) : Operation(parent), memory(_memory), cpu(_cpu)
{
}

OROperation::~OROperation()
{
}

void OROperation::exec(const QString &IR)
{
    bool ok;
    QString SR1 = cpu->getRegister(IR.mid(6, 5).toInt(&ok, 2));
    QString SR2 = cpu->getRegister(IR.mid(11, 5).toInt(&ok, 2));
    QString result = "11111111111111111111111111111111";
    for (int i = 0; i < 32; i++)
    {
        if (SR1.mid(i, 1) == "0" && SR2.mid(i, 1) == "0")
        {
            result.replace(i, 1, "0");
        }
    }
    QString DR = result;
    int DRnum = IR.mid(16, 5).toInt(&ok, 2);
    cpu->setRegisters(DRnum, DR);
}

ORIOperation::ORIOperation(CPU *_cpu, Memory *_memory, QObject *parent) : Operation(parent), memory(_memory), cpu(_cpu)
{
}

ORIOperation::~ORIOperation()
{
}

void ORIOperation::exec(const QString &IR)
{
    bool ok;
    QString SR1 = cpu->getRegister(IR.mid(6, 5).toInt(&ok, 2));
    QString SR2 = IR.mid(16, 16);
    if (SR2.mid(0, 1) == "0")
    {
        SR2.prepend("0000000000000000");
    }
    else
    {
        SR2.prepend("1111111111111111");
    }
    QString result = "11111111111111111111111111111111";
    for (int i = 0; i < 32; i++)
    {
        if (SR1.mid(i, 1) == "0" && SR2.mid(i, 1) == "0")
            result.replace(i, 1, "0");
    }
    QString DR = result;
    int DRnum = IR.mid(11, 5).toInt(&ok, 2);
    cpu->setRegisters(DRnum, DR);
}

XOROperation::XOROperation(CPU *_cpu, Memory *_memory, QObject *parent) : Operation(parent), memory(_memory), cpu(_cpu)
{
}

XOROperation::~XOROperation()
{
}

void XOROperation::exec(const QString &IR)
{
    bool ok;
    QString SR1 = cpu->getRegister(IR.mid(6, 5).toInt(&ok, 2));
    QString SR2 = cpu->getRegister(IR.mid(11, 5).toInt(&ok, 2));
    QString result = "11111111111111111111111111111111";
    for (int i = 0; i < 32; i++)
    {
        if (SR1.mid(i, 1) == SR2.mid(i, 1))
        {
            result.replace(i, 1, "0");
        }
    }
    QString DR = result;
    int DRnum = IR.mid(16, 5).toInt(&ok, 2);
    cpu->setRegisters(DRnum, DR);
}

XORIOperation::XORIOperation(CPU *_cpu, Memory *_memory, QObject *parent) : Operation(parent), memory(_memory), cpu(_cpu)
{
}

XORIOperation::~XORIOperation()
{
}

void XORIOperation::exec(const QString &IR)
{
    bool ok;
    QString SR1 = cpu->getRegister(IR.mid(6, 5).toInt(&ok, 2));
    QString SR2 = IR.mid(16, 16);
    if (SR2.mid(0, 1) == "0")
    {
        SR2.prepend("0000000000000000");
    }
    else
    {
        SR2.prepend("1111111111111111");
    }
    QString result = "11111111111111111111111111111111";
    for (int i = 0; i < 32; i++)
    {
        if (SR1.mid(i, 1) == SR2.mid(i, 1))
        {
            result.replace(i, 1, "0");
        }
    }
    QString DR = result;
    int DRnum = IR.mid(11, 5).toInt(&ok, 2);
    cpu->setRegisters(DRnum, DR);
}

LHIOperation::LHIOperation(CPU *_cpu, Memory *_memory, QObject *parent) : Operation(parent), memory(_memory), cpu(_cpu)
{
}

LHIOperation::~LHIOperation()
{
}

void LHIOperation::exec(const QString &IR)
{
    QString temp = IR.mid(16);
    QString DR = temp + "0000000000000000";
    bool ok;
    int DRnum = IR.mid(11, 5).toInt(&ok, 2);
    cpu->setRegisters(DRnum, DR);
}

SLLOperation::SLLOperation(CPU *_cpu, Memory *_memory, QObject *parent) : Operation(parent), memory(_memory), cpu(_cpu)
{
}

SLLOperation::~SLLOperation()
{
}

void SLLOperation::exec(const QString &IR)
{
    bool ok;
    QString SR1 = cpu->getRegister(IR.mid(6, 5).toInt(&ok, 2));
    QString SR2 = cpu->getRegister(IR.mid(11, 5).toInt(&ok, 2));
    quint32 offset = Utilities::binToUDec(SR2);
    if (offset < static_cast<quint32>(32))
    {
        SR1 = SR1.mid(offset);

        for (quint32 i = 0; i < offset; i++)
        {
            SR1.append("0");
        }
    }
    else
    {
        SR1 = "00000000000000000000000000000000";
    }
    QString DR = SR1;
    int DRnum = IR.mid(16, 5).toInt(&ok, 2);
    cpu->setRegisters(DRnum, DR);
}

SLLIOperation::SLLIOperation(CPU *_cpu, Memory *_memory, QObject *parent) : Operation(parent), memory(_memory), cpu(_cpu)
{
}

SLLIOperation::~SLLIOperation()
{
}

void SLLIOperation::exec(const QString &IR)
{
    bool ok;
    QString SR1 = cpu->getRegister(IR.mid(6, 5).toInt(&ok, 2));
    QString SR2 = IR.mid(16);
    quint32 offset = Utilities::binToUDec(SR2);
    if(offset < static_cast<quint32>(32))
    {
        SR1 = SR1.mid(offset);
        for (quint32 i = 0; i < offset; i++)
        {
            SR1.append("0");
        }
    }
    else
    {
        SR1 = "00000000000000000000000000000000";
    }
    QString DR = SR1;
    int DRnum = IR.mid(11, 5).toInt(&ok, 2);
    cpu->setRegisters(DRnum, DR);
}

SRLOperation::SRLOperation(CPU *_cpu, Memory *_memory, QObject *parent) : Operation(parent), memory(_memory), cpu(_cpu)
{
}

SRLOperation::~SRLOperation()
{
}

void SRLOperation::exec(const QString &IR)
{
    bool ok;
    QString SR1 = cpu->getRegister(IR.mid(6, 5).toInt(&ok, 2));
    QString SR2 = cpu->getRegister(IR.mid(11, 5).toInt(&ok, 2));
    quint32 offset = Utilities::binToUDec(SR2);
    if(offset < static_cast<quint32>(32))
    {
        SR1 = SR1.mid(0, SR2.length() - offset);
        for (quint32 i = 0; i < offset; i++)
        {
            SR1.prepend("0");
        }
    }
    else
    {
        SR1 = "00000000000000000000000000000000";
    }
    QString DR = SR1;
    int DRnum = IR.mid(16, 5).toInt(&ok, 2);
    cpu->setRegisters(DRnum, DR);
}

SRLIOperation::SRLIOperation(CPU *_cpu, Memory *_memory, QObject *parent) : Operation(parent), memory(_memory), cpu(_cpu)
{
}

SRLIOperation::~SRLIOperation()
{
}

void SRLIOperation::exec(const QString &IR)
{
    bool ok;
    QString SR1 = cpu->getRegister(IR.mid(6, 5).toInt(&ok, 2));
    QString SR2 = IR.mid(16);
    quint32 offset = Utilities::binToUDec(SR2);
    if(offset < static_cast<quint32>(32))
    {
        SR1 = SR1.mid(0, SR2.length() - offset);
        for (quint32 i = 0; i < offset; i++)
        {
            SR1.prepend("0");
        }
    }
    else
    {
        SR1 = "00000000000000000000000000000000";
    }
    QString DR = SR1;
    int DRnum = IR.mid(11, 5).toInt(&ok, 2);
    cpu->setRegisters(DRnum, DR);
}

SRAOperation::SRAOperation(CPU *_cpu, Memory *_memory, QObject *parent) : Operation(parent), memory(_memory), cpu(_cpu)
{
}

SRAOperation::~SRAOperation()
{
}

void SRAOperation::exec(const QString &IR)
{
    bool ok;
    QString SR1 = cpu->getRegister(IR.mid(6, 5).toInt(&ok, 2));
    QString SR2 = cpu->getRegister(IR.mid(11, 5).toInt(&ok, 2));
    quint32 offset = Utilities::binToUDec(SR2);
    if(offset < static_cast<quint32>(32))
    {
        SR1 = SR1.mid(0, SR2.length() - offset);
        QString signBit = SR1.mid(0, 1);
        for (quint32 i = 0; i < offset; i++)
        {
            SR1.prepend(signBit);
        }
    }
    else
    {
        if(SR1.startsWith("0"))
        {
            SR1 = "00000000000000000000000000000000";
        }
        else
        {
            SR1 = "11111111111111111111111111111111";
        }
    }
    QString DR = SR1;
    int DRnum = IR.mid(16, 5).toInt(&ok, 2);
    cpu->setRegisters(DRnum, DR);
}

SRAIOperation::SRAIOperation(CPU *_cpu, Memory *_memory, QObject *parent) : Operation(parent), memory(_memory), cpu(_cpu)
{
}

SRAIOperation::~SRAIOperation()
{
}

void SRAIOperation::exec(const QString &IR)
{
    bool ok;
    QString SR1 = cpu->getRegister(IR.mid(6, 5).toInt(&ok, 2));
    QString SR2 = IR.mid(16);
    quint32 offset = Utilities::binToUDec(SR2);
    if(offset < static_cast<quint32>(32))
    {
        SR1 = SR1.mid(0, SR2.length() - offset);
        QString signBit = SR1.mid(0, 1);
        for (quint32 i = 0; i < offset; i++)
        {
            SR1.prepend(signBit);
        }
    }
    else
    {
        if(SR1.startsWith("0"))
        {
            SR1 = "00000000000000000000000000000000";
        }
        else
        {
            SR1 = "11111111111111111111111111111111";
        }
    }
    QString DR = SR1;
    int DRnum = IR.mid(11, 5).toInt(&ok, 2);
    cpu->setRegisters(DRnum, DR);
}

SLTOperation::SLTOperation(CPU *_cpu, Memory *_memory, QObject *parent) : Operation(parent), memory(_memory), cpu(_cpu)
{
}

SLTOperation::~SLTOperation()
{
}

void SLTOperation::exec(const QString &IR)
{
    bool ok;
    QString SR1 = cpu->getRegister(IR.mid(6, 5).toInt(&ok, 2));
    QString SR2 = cpu->getRegister(IR.mid(11, 5).toInt(&ok, 2));
    int offset = Utilities::binToDec(SR1) - Utilities::binToDec(SR2);
    QString DR;
    if (offset < 0)
    {
        DR = "00000000000000000000000000000001";
    }
    else
    {
        DR = "00000000000000000000000000000000";
    }
    int DRnum = IR.mid(16, 5).toInt(&ok, 2);
    cpu->setRegisters(DRnum, DR);
}

SLTIOperation::SLTIOperation(CPU *_cpu, Memory *_memory, QObject *parent) : Operation(parent), memory(_memory), cpu(_cpu)
{
}

SLTIOperation::~SLTIOperation()
{
}

void SLTIOperation::exec(const QString &IR)
{
    bool ok;
    QString SR1 = cpu->getRegister(IR.mid(6, 5).toInt(&ok, 2));
    QString SR2 = IR.mid(16);
    int offset = Utilities::binToDec(SR1) - Utilities::binToDec(SR2);
    QString DR;
    if (offset < 0)
    {
        DR = "00000000000000000000000000000001";
    }
    else
    {
        DR = "00000000000000000000000000000000";
    }
    int DRnum = IR.mid(11, 5).toInt(&ok, 2);
    cpu->setRegisters(DRnum, DR);
}

SLEOperation::SLEOperation(CPU *_cpu, Memory *_memory, QObject *parent) : Operation(parent), memory(_memory), cpu(_cpu)
{
}

SLEOperation::~SLEOperation()
{
}

void SLEOperation::exec(const QString &IR)
{
    bool ok;
    QString SR1 = cpu->getRegister(IR.mid(6, 5).toInt(&ok, 2));
    QString SR2 = cpu->getRegister(IR.mid(11, 5).toInt(&ok, 2));
    int offset = Utilities::binToDec(SR1) - Utilities::binToDec(SR2);
    QString DR;
    if (offset <= 0)
    {
        DR = "00000000000000000000000000000001";
    }
    else
    {
        DR = "00000000000000000000000000000000";
    }
    int DRnum = IR.mid(16, 5).toInt(&ok, 2);
    cpu->setRegisters(DRnum, DR);
}

SLEIOperation::SLEIOperation(CPU *_cpu, Memory *_memory, QObject *parent) : Operation(parent), memory(_memory), cpu(_cpu)
{
}

SLEIOperation::~SLEIOperation()
{
}

void SLEIOperation::exec(const QString &IR)
{
    bool ok;
    QString SR1 = cpu->getRegister(IR.mid(6, 5).toInt(&ok, 2));
    QString SR2 = IR.mid(16);
    int offset = Utilities::binToDec(SR1) - Utilities::binToDec(SR2);
    QString DR;
    if (offset <= 0)
    {
        DR = "00000000000000000000000000000001";
    }
    else
    {
        DR = "00000000000000000000000000000000";
    }
    int DRnum = IR.mid(11, 5).toInt(&ok, 2);
    cpu->setRegisters(DRnum, DR);
}

SEQOperation::SEQOperation(CPU *_cpu, Memory *_memory, QObject *parent) : Operation(parent), memory(_memory), cpu(_cpu)
{
}

SEQOperation::~SEQOperation()
{
}

void SEQOperation::exec(const QString &IR)
{
    bool ok;
    QString SR1 = cpu->getRegister(IR.mid(6, 5).toInt(&ok, 2));
    QString SR2 = cpu->getRegister(IR.mid(11, 5).toInt(&ok, 2));
    int offset = Utilities::binToDec(SR1) - Utilities::binToDec(SR2);
    QString DR;
    if (offset == 0)
    {
        DR = "00000000000000000000000000000001";
    }
    else
    {
        DR = "00000000000000000000000000000000";
    }
    int DRnum = IR.mid(16, 5).toInt(&ok, 2);
    cpu->setRegisters(DRnum, DR);
}

SEQIOperation::SEQIOperation(CPU *_cpu, Memory *_memory, QObject *parent) : Operation(parent), memory(_memory), cpu(_cpu)
{
}

SEQIOperation::~SEQIOperation()
{
}

void SEQIOperation::exec(const QString &IR)
{
    bool ok;
    QString SR1 = cpu->getRegister(IR.mid(6, 5).toInt(&ok, 2));
    QString SR2 = IR.mid(16);
    int offset = Utilities::binToDec(SR1) - Utilities::binToDec(SR2);
    QString DR;
    if (offset == 0)
    {
        DR = "00000000000000000000000000000001";
    }
    else
    {
        DR = "00000000000000000000000000000000";
    }
    int DRnum = IR.mid(11, 5).toInt(&ok, 2);
    cpu->setRegisters(DRnum, DR);
}

SNEOperation::SNEOperation(CPU *_cpu, Memory *_memory, QObject *parent) : Operation(parent), memory(_memory), cpu(_cpu)
{
}

SNEOperation::~SNEOperation()
{
}

void SNEOperation::exec(const QString &IR)
{
    bool ok;
    QString SR1 = cpu->getRegister(IR.mid(6, 5).toInt(&ok, 2));
    QString SR2 = cpu->getRegister(IR.mid(11, 5).toInt(&ok, 2));
    int offset = Utilities::binToDec(SR1) - Utilities::binToDec(SR2);
    QString DR;
    if (offset != 0)
    {
        DR = "00000000000000000000000000000001";
    }
    else
    {
        DR = "00000000000000000000000000000000";
    }
    int DRnum = IR.mid(16, 5).toInt(&ok, 2);
    cpu->setRegisters(DRnum, DR);
}

SNEIOperation::SNEIOperation(CPU *_cpu, Memory *_memory, QObject *parent) : Operation(parent), memory(_memory), cpu(_cpu)
{
}

SNEIOperation::~SNEIOperation()
{
}

void SNEIOperation::exec(const QString &IR)
{
    bool ok;
    QString SR1 = cpu->getRegister(IR.mid(6, 5).toInt(&ok, 2));
    QString SR2 = IR.mid(16);
    int offset = Utilities::binToDec(SR1) - Utilities::binToDec(SR2);
    QString DR;
    if (offset != 0)
    {
        DR = "00000000000000000000000000000001";
    }
    else
    {
        DR = "00000000000000000000000000000000";
    }
    int DRnum = IR.mid(11, 5).toInt(&ok, 2);
    cpu->setRegisters(DRnum, DR);
}

LWOperation::LWOperation(CPU *_cpu, Memory *_memory, QObject *parent) : Operation(parent), memory(_memory), cpu(_cpu)
{
}

LWOperation::~LWOperation()
{
}

void LWOperation::exec(const QString &IR)
{
    bool ok;
    QString SR1 = cpu->getRegister(IR.mid(6, 5).toInt(&ok, 2));
    QString SR2 = IR.mid(16);
    quint32 midResult = Utilities::binToUDec(SR1) + Utilities::binToDec(SR2);
    QString DR;
    for(int i = 0; i < 4; i++)
    {
        DR.append(memory->read(midResult + i));
    }
    int DRnum = IR.mid(11, 5).toInt(&ok, 2);
    cpu->setRegisters(DRnum, DR);
}

SWOperation::SWOperation(CPU *_cpu, Memory *_memory, QObject *parent) : Operation(parent), memory(_memory), cpu(_cpu)
{
}

SWOperation::~SWOperation()
{
}

void SWOperation::exec(const QString &IR)
{
    bool ok;
    QString SR1 = cpu->getRegister(IR.mid(6, 5).toInt(&ok, 2));
    QString SR2 = IR.mid(16);
    quint32 midResult = Utilities::binToUDec(SR1) + Utilities::binToDec(SR2);
    QString DR = cpu->getRegister(IR.mid(11, 5).toInt(&ok, 2));
    for(int i = 0; i < 4; i++)
    {
        memory->write(midResult + i, DR.mid(i * 8, 8));
    }
}

LBOperation::LBOperation(CPU *_cpu, Memory *_memory, QObject *parent) : Operation(parent), memory(_memory), cpu(_cpu)
{
}

LBOperation::~LBOperation()
{
}

void LBOperation::exec(const QString &IR)
{
    bool ok;
    QString SR1 = cpu->getRegister(IR.mid(6, 5).toInt(&ok, 2));
    QString SR2 = IR.mid(16);
    quint32 midResult = Utilities::binToUDec(SR1) + Utilities::binToDec(SR2);
    QString DR = Utilities::signExtend(memory->read(midResult));
    int DRnum = IR.mid(11, 5).toInt(&ok, 2);
    cpu->setRegisters(DRnum, DR);
}

SBOperation::SBOperation(CPU *_cpu, Memory *_memory, QObject *parent) : Operation(parent), memory(_memory), cpu(_cpu)
{
}

SBOperation::~SBOperation()
{
}

void SBOperation::exec(const QString &IR)
{
    bool ok;
    QString SR1 = cpu->getRegister(IR.mid(6, 5).toInt(&ok, 2));
    QString SR2 = IR.mid(16);
    quint32 midResult = Utilities::binToUDec(SR1) + Utilities::binToDec(SR2);
    QString DR = cpu->getRegister(IR.mid(11, 5).toInt(&ok, 2));
    memory->write(midResult, DR.mid(24));
}


BEQZOperation::BEQZOperation(CPU *_cpu, Memory *_memory, QObject *parent) : Operation(parent), memory(_memory), cpu(_cpu)
{
}

BEQZOperation::~BEQZOperation()
{
}

void BEQZOperation::exec(const QString &IR)
{
    bool ok;
    QString SR1 = cpu->getRegister(IR.mid(6, 5).toInt(&ok, 2));
    if (Utilities::binToDec(SR1) != 0)
    {
        return;
    }
    QString SR2 = IR.mid(16);
    quint32 newPC = cpu->getPC() +  Utilities::binToDec(SR2);
    cpu->setPC(newPC);
}

BNEZOperation::BNEZOperation(CPU *_cpu, Memory *_memory, QObject *parent) : Operation(parent), memory(_memory), cpu(_cpu)
{
}

BNEZOperation::~BNEZOperation()
{
}

void BNEZOperation::exec(const QString &IR)
{
    bool ok;
    QString SR1 = cpu->getRegister(IR.mid(6, 5).toInt(&ok, 2));
    if (Utilities::binToDec(SR1) == 0)
    {
        return;
    }
    QString SR2 = IR.mid(16);
    quint32 newPC = cpu->getPC() +  Utilities::binToDec(SR2);
    cpu->setPC(newPC);
}

JOperation::JOperation(CPU *_cpu, Memory *_memory, QObject *parent) : Operation(parent), memory(_memory), cpu(_cpu)
{
}

JOperation::~JOperation()
{
}

void JOperation::exec(const QString &IR)
{
    int offset = Utilities::binToDec(IR.mid(6));
    quint32 newPC = cpu->getPC() + offset;
    cpu->setPC(newPC);
}

JROperation::JROperation(CPU *_cpu, Memory *_memory, QObject *parent) : Operation(parent), memory(_memory), cpu(_cpu)
{
}

JROperation::~JROperation()
{
}

void JROperation::exec(const QString &IR)
{
    bool ok;
    QString SR1 = cpu->getRegister(IR.mid(6, 5).toInt(&ok, 2));
    quint32 newPC = Utilities::binToUDec(SR1);
    cpu->setPC(newPC);
}

JALOperation::JALOperation(CPU *_cpu, Memory *_memory, QObject *parent) : Operation(parent), memory(_memory), cpu(_cpu)
{
}

JALOperation::~JALOperation()
{
}

void JALOperation::exec(const QString &IR)
{
    cpu->setRegisters(31, Utilities::decToBin(cpu->getPC()));
    int offset = Utilities::binToDec(IR.mid(6));
    quint32 newPC = cpu->getPC() + offset;
    cpu->setPC(newPC);
}

JALROperation::JALROperation(CPU *_cpu, Memory *_memory, QObject *parent) : Operation(parent), memory(_memory), cpu(_cpu)
{
}

JALROperation::~JALROperation()
{
}

void JALROperation::exec(const QString &IR)
{
    cpu->setRegisters(31, Utilities::decToBin(cpu->getPC()));
    bool ok;
    QString SR1 = cpu->getRegister(IR.mid(6, 5).toInt(&ok, 2));
    quint32 newPC = Utilities::binToUDec(SR1);
    cpu->setPC(newPC);
}

TRAPOperation::TRAPOperation(CPU *_cpu, Memory *_memory, QObject *parent) : Operation(parent), memory(_memory), cpu(_cpu)
{
}

TRAPOperation::~TRAPOperation()
{
}

void TRAPOperation::exec(const QString &IR)
{
    QString trap = IR.mid(6);
    bool ok;
    quint32 trapIndex = static_cast<quint32>(trap.toInt(&ok, 2));
    trapIndex *= 4;
    QString trapAddress;
    for(int i = 0; i < 4; i++)
    {
        trapAddress.append(memory->read(trapIndex + i));
    }
    cpu->setRegisters(31, Utilities::decToBin(cpu->getPC()));
    cpu->setPC(Utilities::binToUDec(trapAddress));
}

XFEOperation::XFEOperation(CPU *_cpu, Memory *_memory, QObject *parent) : Operation(parent), memory(_memory), cpu(_cpu)
{
}

XFEOperation::~XFEOperation()
{
}

void XFEOperation::exec(const QString &IR)
{
    Q_UNUSED(IR);
}
